package com.hsy.leancloudchat

import android.content.Context
import android.util.Log
import android.widget.Toast
import androidx.lifecycle.MutableLiveData
import cn.leancloud.LCObject
import cn.leancloud.LCQuery
import cn.leancloud.LCUser
import cn.leancloud.im.v2.LCIMClient
import cn.leancloud.im.v2.LCIMConversation
import cn.leancloud.im.v2.LCIMException
import cn.leancloud.im.v2.LCIMMessage
import cn.leancloud.im.v2.callback.LCIMClientCallback
import cn.leancloud.im.v2.callback.LCIMConversationCallback
import cn.leancloud.im.v2.callback.LCIMConversationCreatedCallback
import cn.leancloud.im.v2.callback.LCIMConversationQueryCallback
import cn.leancloud.im.v2.callback.LCIMMessagesQueryCallback
import cn.leancloud.im.v2.messages.LCIMTextMessage
import io.reactivex.Observer
import io.reactivex.disposables.Disposable
import org.json.JSONObject
import java.text.SimpleDateFormat
import java.util.Date

class LeanCloudHelper private constructor() {
    companion object {
        private var instance: LeanCloudHelper? = null
        fun getInstance(): LeanCloudHelper {
            if (instance == null) {
                synchronized(this) {
                    if (instance == null) {
                        instance = LeanCloudHelper()
                    }
                }
            }
            return instance!!
        }

        val mCurrentClientLiveData = MutableLiveData<LCIMClient>()

        // 最近点进去的 conversation
        var mLastPickConversation: LCIMConversation? = null // todo --- del
    }

    /** 根据 userName和 password登录 */
    fun loginIMByUserNameAndPassword(
        userName: String,
        password: String,
        context: Context,
        onSuccess: () -> Unit
    ) {
        LCUser.logIn(userName, password).subscribe(object : Observer<LCUser> {
            override fun onSubscribe(d: Disposable) {
            }

            override fun onError(e: Throwable) {
                Toast(context).apply {
                    setText("$e")
                    show()
                }
                Log.v("hsy111", e.toString())
            }

            override fun onComplete() {
            }

            override fun onNext(user: LCUser) {
                val client = LCIMClient.getInstance(user)
                client?.open(object : LCIMClientCallback() {
                    override fun done(client: LCIMClient?, e: LCIMException?) {
                        if (e == null) {
                            Toast(context).apply {
                                setText("用户 - ${LCUser.currentUser().username}登录 LeanCloud成功")
                                show()
                            }
                            mCurrentClientLiveData.postValue(client!!)
                            onSuccess()
                        } else {
                            Toast(context).apply {
                                setText("登录失败")
                                show()
                            }
                        }
                    }
                })
            }
        })
    }

    /** 在数据库中存 _User */
    fun saveUserInBackground(user: LCUser, context: Context) {
        Log.v(
            "hsy111",
            "userName -> ${user.username}   pwd -> ${user.password}"
        )
        user.saveInBackground().subscribe(object : Observer<LCObject> {
            override fun onSubscribe(d: Disposable) {
            }

            override fun onError(e: Throwable) {
                Toast(context).apply {
                    setText("注册失败 -> $e")
                    show()
                }
                Log.v("hsy111", "onError -> $e")
            }

            override fun onComplete() {
            }

            override fun onNext(t: LCObject) {
                Toast(context).apply {
                    setText("注册成功 -> ${(t as LCUser).username}")
                    show()
                }
                Log.v("hsy111", "onNext -> ${(t as LCUser).username}")
            }
        })
    }

    /** 从 LeanCloud数据库中查询 _User */
    fun getUserInBackGround(
        clientId: String,
        foundUserLiveData: MutableLiveData<LCUser?>
    ) {
        val query = LCQuery<LCUser>("_User")
        query.getInBackground(clientId).subscribe(object : Observer<LCUser> {
            override fun onSubscribe(d: Disposable) {
            }

            override fun onError(e: Throwable) {
                foundUserLiveData.postValue(null)
            }

            override fun onComplete() {
            }

            override fun onNext(lcUser: LCUser) {
                foundUserLiveData.postValue(lcUser)
            }
        })
    }

    /** 从 LeanCloud数据库查询与当前用户有关的 conversation，并分为 请求和 已有会话 */
    fun queryConversationContainCurrentClient(
        client: LCIMClient,
        requestConversationListLiveData: MutableLiveData<MutableList<LCIMConversation>>,
        existConversationListLiveData: MutableLiveData<MutableList<LCIMConversation>>
    ) {
        val query = client.conversationsQuery
        query.whereContains("m", mCurrentClientLiveData.value?.clientId)
        query.isWithLastMessagesRefreshed = true
        query.findInBackground(object : LCIMConversationQueryCallback() {
            override fun done(conversations: MutableList<LCIMConversation>?, e: LCIMException?) {
                if (e == null) {
                    Log.v(
                        "hsy111",
                        "lastMessage -> " + conversations?.get(0)?.lastMessage?.content.toString()
                    )
                    val requestConversationList = mutableListOf<LCIMConversation>()
                    val existConversationList = mutableListOf<LCIMConversation>()
                    conversations?.forEach {
                        if (it.lastMessage == null && it.creator != client.clientId) {
                            // 一条消息都没有，且不是自己创建的 conversation，说明是好友请求
                            requestConversationList.add(it)
                        } else if (it.lastMessage != null) {
                            Log.v("hsy111", "conversation.last -> ${it.lastMessage.content}")
                            // 有至少一条消息，说明是已通过的 conversation
                            existConversationList.add(it)
                        }
                    }
                    requestConversationListLiveData.postValue(requestConversationList)
                    existConversationListLiveData.postValue(existConversationList)
                } else {
                    Log.v("hsy111", "queryConversationContainCurrentClient 失败 -> $e")
                }
            }
        })
    }

    /** 创建 Conversation，如果已有则返回已有的，否则新建 */
    fun createConversation(
        client: LCIMClient,
        members: MutableList<String>,
        name: String,
        context: Context,
        onSuccess: (LCIMConversation) -> Unit
    ) {
        client.createConversation(
            members,
            name,
            null,
            false,
            true,
            object : LCIMConversationCreatedCallback() {
                override fun done(conversation: LCIMConversation?, e: LCIMException?) {
                    if (e == null) {
                        conversation?.let(onSuccess)
                    } else {
                        Toast(context).apply {
                            setText(e.toString())
                            show()
                        }
                        Log.v("hsy111", e.toString())
                    }
                }
            })
    }

    /** 根据 id获取 conversation */
    fun getConversationById(
        conversationId: String,
        conversationLiveData: MutableLiveData<LCIMConversation>,
        context: Context
    ) {
        val query = mCurrentClientLiveData.value?.conversationsQuery
        query?.whereEqualTo("objectId", conversationId)
        query?.findInBackground(object : LCIMConversationQueryCallback() {
            override fun done(conversations: MutableList<LCIMConversation>?, e: LCIMException?) {
                if (e == null) {
                    conversationLiveData.postValue(conversations?.get(0))
                } else {
                    Toast(context).apply {
                        setText("getConversationById 失败")
                        show()
                    }
                }
            }
        })
    }

    /** 发消息 */
    fun sendMessage(
        conversation: LCIMConversation,
        msg: String,
        lastMessageLiveData: MutableLiveData<LCIMMessage> = MutableLiveData(),
        context: Context
    ) {
        val message = LCIMTextMessage().apply {
            text = msg
        }
        conversation.sendMessage(message, object : LCIMConversationCallback() {
            override fun done(e: LCIMException?) {
                if (e == null) {
                    Toast(context).apply {
                        setText("发送成功")
                        show()
                    }
                    lastMessageLiveData.postValue(conversation.lastMessage)
                }
            }
        })
    }

    /** 通过 conversation查询历史消息 */
    fun getHistoryMessages(
        conversation: LCIMConversation,
        messageCount: Int,
        messagesLiveData: MutableLiveData<MutableList<LCIMMessage>>,
        context: Context
    ) {
        conversation.queryMessages(
            messageCount, object : LCIMMessagesQueryCallback() {
                override fun done(messages: MutableList<LCIMMessage>?, e: LCIMException?) {
                    if (e == null) {
                        val originMessages = messagesLiveData.value
                        if (originMessages != null && messages != null) {
                            originMessages += messages
                        }
                        messagesLiveData.postValue(originMessages)
                    } else {
                        Toast(context).apply {
                            setText("getHistoryMessages 失败")
                            show()
                        }
                        Log.v("hsy111", e.toString())
                    }
                }
            }
        )
    }

    /** 解析时间戳 */
    fun parseTimeStamp(timeStamp: Long): String {
        val dateFormat = SimpleDateFormat("MM/dd\nHH:mm:ss")
        val date = Date(timeStamp)
        return dateFormat.format(date)
    }

    /** 解析 Message获得 Text */
    fun parseMessageContentForText(messageContent: String): String {
        return JSONObject(messageContent).getString("_lctext")
    }
}